package com.lw.smartquiz.assess;

import cn.hutool.json.JSONUtil;
import com.lw.smartquiz.common.ErrorCode;
import com.lw.smartquiz.exception.ThrowUtils;
import com.lw.smartquiz.model.dto.question.QuestionContentDTO;
import com.lw.smartquiz.model.entity.App;
import com.lw.smartquiz.model.entity.Question;
import com.lw.smartquiz.model.entity.ScoringResult;
import com.lw.smartquiz.model.entity.UserAnswer;
import com.lw.smartquiz.model.enums.AppTypeEnum;
import com.lw.smartquiz.model.enums.ScoringStrategyEnum;
import com.lw.smartquiz.model.vo.QuestionVO;
import com.lw.smartquiz.model.vo.ScoringResultVO;
import com.lw.smartquiz.service.QuestionService;
import com.lw.smartquiz.service.ScoringResultService;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 自定义的测评类应用的评判策略
 */
@AssessStrategyConfig(appType = AppTypeEnum.TEST, strategyType = ScoringStrategyEnum.CUSTOM)
public class CustomTestAssessStrategy implements AssessStrategy {
    @Resource
    private QuestionService questionService;
    @Resource
    private ScoringResultService scoringResultService;

    @Override
    public UserAnswer doScore(List<String> choices, App app) {
        // 1.根据app获取题目和所有的结果属性集
        Long appId = app.getId();
        Question question = questionService.lambdaQuery().eq(Question::getAppId, appId).one();
        QuestionVO questionVO = QuestionVO.objToVo(question);
        List<QuestionContentDTO> questionList = questionVO.getQuestionContent();
        List<ScoringResult> scoringResultList = scoringResultService.lambdaQuery().eq(ScoringResult::getAppId, appId).list();

        // 2.统计每种属性用户的选择个数
        Map<String, Integer> propCount = new HashMap<>();
        int size = choices.size();
        for (int i = 0; i < size; i++) {
            //用户这一题的选择
            String choice = choices.get(i);
            //这一题的所有选项
            List<QuestionContentDTO.Option> options = questionList.get(i).getOptions();
            for (QuestionContentDTO.Option option : options) {
                // 如果用户选择了这个选项，则该选项对应的属性的计数加一
                if (choice.equals(option.getKey())) {
                    String result = option.getResult();
                    propCount.put(result, propCount.getOrDefault(result, 0) + 1);
                    break;
                }
            }
        }

        // 3.遍历每种属性集，计算得分最高的属性集，即为结果
        // 最高的属性集的得分和
        int maxScore = 0;
        // 最高得分和的结果
        ScoringResult maxResult = null;

        // 遍历所有结果，找到得分最高的属性集
        for (ScoringResult scoringResult : scoringResultList) {
            // 转成更利于操作的vo再获取这个结果的属性集
            ScoringResultVO scoringResultVO = ScoringResultVO.objToVo(scoringResult);
            List<String> resultProp = scoringResultVO.getResultProp();
            // 计算这个属性集的总选择次数
            int sum = resultProp.stream().mapToInt(prop -> propCount.getOrDefault(prop, 0)).sum();
            // 更新最高分，最高分的属性集
            if(sum > maxScore){
                maxScore = sum;
                maxResult = scoringResult;
            }
        }
        // 如果没有找到最高分，则抛出异常
        ThrowUtils.throwIf(maxResult == null, ErrorCode.OPERATION_ERROR);

        // 4.填充用户答案
        UserAnswer userAnswer = new UserAnswer();
        userAnswer.setAppId(appId);
        userAnswer.setAppType(app.getAppType());
        userAnswer.setScoringStrategy(app.getScoringStrategy());
        userAnswer.setChoices(JSONUtil.toJsonStr(choices));
        userAnswer.setResultId(maxResult.getId());
        userAnswer.setResultName(maxResult.getResultName());
        userAnswer.setResultDesc(maxResult.getResultDesc());
        userAnswer.setResultPicture(maxResult.getResultPicture());

        return userAnswer;
    }
}
